﻿using LxBasic;

namespace LxLESS
{
    public partial class MGJoint : IBuildMGJoint, IJointIteration
    {
        // 这部分字段不是通过方法设置的，而是直接设置
        //local
        public MGJoiFace[] JoiFaces;
        public IndexRange FaceIdx => new IndexRange(JoiFaces.Length);
        //share
        public MGZone O_Zone;
        public IndexRange O_BouIndex;

        public MGZone N_Zone;
        public IndexRange N_BouIndex;

        #region IBuildMGJoint
        IEnumerable<int> IBuildMGJoint.GetOZoneSideJoints(int sideId)
        {
            return O_Zone.BouFaces[sideId].Joints;
        }
        IEnumerable<int> IBuildMGJoint.GetNZoneSideJoints(int sideId)
        {
            return N_Zone.BouFaces[sideId].Joints;
        }
        IndexRange IBuildMGJoint.GetFaceIdx()
        {
            return FaceIdx;
        }
        #endregion

        public LESSJoint InLESSJoint;

        public double[] O_JoiAH;//存储系数，zone中的AH存储交界面临时结果
        public double[] N_JoiAH;

        public void SetArray(LESSJoint inLESSJoint)
        {
            this.InLESSJoint = inLESSJoint;
            CheckCreator.ArrayStrict(ref O_JoiAH, JoiFaces.Length);
            CheckCreator.ArrayStrict(ref N_JoiAH, JoiFaces.Length);
        }
        #region IJointIteration
        public LESSJoint GetLessJoint()
        {
            return InLESSJoint;
        }
        public void AMGIte_Restrict_A(ThreadInfo threadInfo)
        {
            var coarse = InLESSJoint.MGJoints[AMGGlobal.SolvingLevel + 1];
            coarse.HelpRestrict_ALU(O_JoiAH, N_JoiAH, threadInfo);
        }
        public void HelpRestrict_ALU(double[] fineALUO, double[] fineALUN, ThreadInfo threadInfo)
        {
            (int i1, int endp1) = FaceIdx.Split(threadInfo);
            for (; i1 < endp1; i1++)
            {
                double aluo = 0, alun = 0;
                foreach (var pid in JoiFaces[i1].FineJoints)
                {
                    aluo += fineALUO[pid];
                    alun += fineALUN[pid];
                }
                O_JoiAH[i1] = aluo;
                N_JoiAH[i1] = alun;
            }
        }
        public void Iterate_Copy_xArray(ThreadInfo threadInfo)
        {
            copyJoint(O_Zone.e, N_Zone.e, threadInfo);
        }
        public void Iterate_Copy_xCommonArray(ThreadInfo threadInfo)
        {
            copyJoint(O_Zone.e_Common, N_Zone.e_Common, threadInfo);
        }
        protected void copyJoint(double[] OArray, double[] NArray, ThreadInfo threadInfo)
        {
            {
                double[] O_ABou = O_Zone.BouAH;
                (int i1, int endp1) = O_BouIndex.Split(threadInfo);
                var O_Sides = O_Zone.BouFaces;
                for (; i1 < endp1; i1++)
                {
                    double aluproduct = 0;
                    foreach (var jid in O_Sides[i1].Joints)
                    {
                        aluproduct += O_JoiAH[jid] * NArray[JoiFaces[jid].N_InnCell];
                    }
                    O_ABou[i1] = aluproduct;
                }
            }
            {
                double[] N_ABou = N_Zone.BouAH;
                (int i1, int endp1) = N_BouIndex.Split(threadInfo);
                var N_Sides = N_Zone.BouFaces;
                for (; i1 < endp1; i1++)
                {
                    double aluproduct = 0;
                    foreach (var jid in N_Sides[i1].Joints)
                    {
                        aluproduct += N_JoiAH[jid] * OArray[JoiFaces[jid].O_InnCell];
                    }
                    N_ABou[i1] = aluproduct;
                }
            }
        }
        public void BiCGStabIte_Copy_yArray(ThreadInfo threadInfo)
        {
            copyJoint(InLESSJoint.O_BiCGZone.y, InLESSJoint.N_BiCGZone.y, threadInfo);
        }
        public void BiCGStabIte_Copy_zArray(ThreadInfo threadInfo)
        {
            copyJoint(InLESSJoint.O_BiCGZone.z, InLESSJoint.N_BiCGZone.z, threadInfo);
        }
        #endregion
    }
}